home *** CD-ROM | disk | FTP | other *** search
- /*
- * cad3d2obj - the Atari CAD-3D file format
- * $Id: cad3dobj.c,v 1.1 1994/03/14 15:22:52 herborth Exp $
- *
- * Chris Herborth
- * March 7/94
- *
- * These are the functions you need to load a CAD-3D 2.x file and do
- * something useful with it. See cad3dobj.h for the structs used
- * here.
- *
- * Compile with -DLITTLE_ENDIAN if you've got a little-endian CPU
- * (ex, Intel, Cyrix, AMD).
- *
- * $Log: cad3dobj.c,v $
- * Revision 1.1 1994/03/14 15:22:52 herborth
- * Initial revision
- *
- */
-
- #include <stdio.h>
- #include "cad3dobj.h"
-
- /* Load the header into our CAD3D_HEADER struct */
- short get_cad3d_header( FILE *fp, CAD3D_HEADER *head )
- {
- short retval;
- #ifdef LITTLE_ENDIAN
- short loop;
- #endif
-
- if( fp == NULL || head == NULL )
- return -1;
-
- retval = fread( head, sizeof( CAD3D_HEADER ), 1, fp );
-
- if( retval != 1 )
- return -1;
-
- /* This is disgusting. I hate Intel. */
- #ifdef LITTLE_ENDIAN
- head->file_id = swap_short( head->file_id );
- head->num_objects = swap_short( head->num_objects );
-
- head->light_a_flag = swap_short( head->light_a_flag );
- head->light_b_flag = swap_short( head->light_b_flag );
- head->light_c_flag = swap_short( head->light_c_flag );
-
- head->light_a_bright = swap_short( head->light_a_bright );
- head->light_b_bright = swap_short( head->light_b_bright );
- head->light_c_bright = swap_short( head->light_c_bright );
- head->ambient_bright = swap_short( head->ambient_bright );
-
- head->light_a_z = swap_short( head->light_a_z );
- head->light_b_z = swap_short( head->light_b_z );
- head->light_c_z = swap_short( head->light_c_z );
- head->light_a_y = swap_short( head->light_a_y );
- head->light_b_y = swap_short( head->light_b_y );
- head->light_c_y = swap_short( head->light_c_y );
- head->light_a_x = swap_short( head->light_a_x );
- head->light_b_x = swap_short( head->light_b_x );
- head->light_c_x = swap_short( head->light_c_x );
-
- for( loop = 0; loop < 16; loop++ )
- head->obj_palette[loop] = swap_short( head->obj_palette[loop] );
-
- for( loop = 0; loop < 16; loop++ )
- head->colour_group[loop] = swap_short( head->colour_group[loop] );
-
- head->palette_type = swap_short( head->palette_type );
- head->wireframe_colour = swap_short( head->wireframe_colour );
- head->outline_colour = swap_short( head->outline_colour );
- #endif
-
- if( head->file_id != CAD3D_MAGIC )
- return -2;
-
- return 0;
- }
-
- /* Dump a CAD-3D 2.x header in a human-readable format to a stream */
- short dump_cad3d_header( FILE *fp, const CAD3D_HEADER *head )
- {
- short loop;
-
- if( fp == NULL || head == NULL )
- return -1;
-
- if( head->file_id == CAD3D_MAGIC )
- fprintf( fp, "CAD3D 2.x File\n" );
- else
- fprintf( fp, "WARNING: Unknown file type %x!\n", head->file_id );
-
- fprintf( fp, "%d objects\n", head->num_objects );
-
- if( head->light_a_flag == 1 )
- fprintf( fp, "Light A (%f, %f, %f) is on, brightness = %d.\n",
- (float)(head->light_a_x)/100.0,
- (float)(head->light_a_y)/100.0,
- (float)(head->light_a_z)/100.0, head->light_a_bright );
- else
- fprintf( fp, "Light A is off.\n" );
-
- if( head->light_b_flag == 1 )
- fprintf( fp, "Light B (%f, %f, %f) is on, brightness = %d.\n",
- (float)(head->light_b_x)/100.0,
- (float)(head->light_b_y)/100.0,
- (float)(head->light_b_z)/100.0, head->light_b_bright );
- else
- fprintf( fp, "Light B is off.\n" );
-
- if( head->light_c_flag == 1 )
- fprintf( fp, "Light C (%f, %f, %f) is on, brightness = %d.\n",
- (float)(head->light_c_x)/100.0,
- (float)(head->light_c_y)/100.0,
- (float)(head->light_c_z)/100.0, head->light_c_bright );
- else
- fprintf( fp, "Light C is off.\n" );
-
- fprintf( fp, "Ambient light brightness = %d.\n", head->ambient_bright );
-
- fprintf( fp, "Colour palette and colour groups:\n" );
- for( loop = 0; loop < 16; loop++ )
- fprintf( fp, "%2d: 0x%04x [%2d]\n", loop, head->obj_palette[loop],
- head->colour_group[loop] );
-
- switch( head->palette_type )
- {
- case 0:
- fprintf( fp, "7-shade palette\n" );
- break;
- case 1:
- fprintf( fp, "14-shade palette\n" );
- break;
- case 2:
- fprintf( fp, "Custom palette\n" );
- break;
- default:
- fprintf( fp, "WARNING: Unknown palette type %d!", head->palette_type );
- break;
- }
-
- fprintf( fp, "Wireframe colour %d\n", head->wireframe_colour );
- fprintf( fp, "Outline colour %d\n", head->outline_colour );
-
- /* char reserved[150]; For future expansion (ha!) */
-
- return 0;
- }
-
- /* Completely load a CAD-3D object from a file, including its vertices */
- /* and triangles... */
- short get_cad3d_object( FILE *fp, CAD3D_OBJECT *obj )
- {
- short retval;
- unsigned short loop;
-
- /* Get the object's name... */
- retval = fread( obj->name, sizeof( char ), 9, fp );
- if( retval != 9 )
- return -1;
-
- /* Get the number of vertices... */
- retval = fread( &(obj->num_vertices), sizeof( short ), 1, fp );
- if( retval != 1 )
- return -1;
- #ifdef LITTLE_ENDIAN
- obj->num_vertices = swap_short( obj->num_vertices );
- #endif
-
- /* Allocate RAM for the vertices and load them... */
- obj->vertices = (CAD3D_VERTEX *)malloc( obj->num_vertices
- * sizeof( CAD3D_VERTEX ) );
- if( obj->vertices == NULL )
- return -2;
-
- for( loop = 0; loop < obj->num_vertices; loop++ )
- {
- retval = get_cad3d_vertex( fp, &(obj->vertices[loop]) );
- if( retval != 0 )
- return -3;
- }
-
- /* Get the number of triangles... */
- retval = fread( &(obj->num_triangles), sizeof( short ), 1, fp );
- #ifdef LITTLE_ENDIAN
- obj->num_triangles = swap_short( obj->num_triangles );
- #endif
-
- /* Allocate memory for the triangles and load them... */
- obj->triangles = (CAD3D_TRIANGLE *)malloc( obj->num_triangles
- * sizeof( CAD3D_TRIANGLE ) );
- if( obj->triangles == NULL )
- return -4;
-
- for( loop = 0; loop < obj->num_triangles; loop++ )
- {
- retval = get_cad3d_triangle( fp, &(obj->triangles[loop]) );
- if( retval != 0 )
- return -5;
- }
-
- return 0;
- }
-
- /* Dump a CAD-3D 2.x in a human-readable format... */
- short dump_cad3d_object( FILE *fp, const CAD3D_OBJECT *obj )
- {
- fprintf( fp, "Object %s:\n", obj->name );
- fprintf( fp, " %d vertices\n", obj->num_vertices );
- fprintf( fp, " %d triangles\n", obj->num_triangles );
- fprintf( fp, " Vertices and triangles mercifully not dumped.\n" );
-
- return 0;
- }
-
- /* Read a vertex from a CAD-3D 2.x object... */
- short get_cad3d_vertex( FILE *fp, CAD3D_VERTEX *vert )
- {
- short retval;
-
- if( fp == NULL || vert == NULL )
- return -1;
-
- retval = fread( vert, sizeof( CAD3D_VERTEX ), 1, fp );
- if( retval != 1 )
- return -2;
-
- #ifdef LITTLE_ENDIAN
- vert->x = swap_short( vert->x );
- vert->y = swap_short( vert->y );
- vert->z = swap_short( vert->z );
- #endif
-
- return 0;
- }
-
- /* Read a triangle within a CAD-3D 2.x object... */
- short get_cad3d_triangle( FILE *fp, CAD3D_TRIANGLE *tri )
- {
- short retval;
-
- if( fp == NULL || tri == NULL )
- return -1;
-
- retval = fread( tri, sizeof( CAD3D_TRIANGLE ), 1, fp );
- if( retval != 1 )
- return -2;
-
- #ifdef LITTLE_ENDIAN
- tri->index_a = swap_short( tri->index_a );
- tri->index_b = swap_short( tri->index_b );
- tri->index_c = swap_short( tri->index_c );
-
- tri->colour_edge = swap_short( tri->colour_edge );
- #endif
-
- return 0;
- }
-
- /* Given a CAD-3D 2.x header and a particular triangle in that object, */
- /* decide which colour is the "base" colour for that object. CAD-3D */
- /* does some shading, which is bogus for rendering; finding the "base" */
- /* colour will allow the renderer to do the shading. Note that this */
- /* "base" colour isn't the same "base" colour referenced in the CAD-3D */
- /* documentation; it's actually the "brightest" of the colours in the */
- /* triangle's colour group. Note also that colours are compared very */
- /* stupidly; a slightly red colour (0x0100) will be "brighter" than a */
- /* very yellow colour (0x0077). If your object has a screwy base */
- /* group arry, it will probably come out all red. */
- short cad3d_triangle_colour( const CAD3D_HEADER *head,
- const CAD3D_TRIANGLE *tri )
- {
- short tri_colour,
- group,
- loop,
- brightest;
-
- /* the low byte of colour_edge is the colour */
- tri_colour = tri->colour_edge & 0x00ff;
- group = head->colour_group[tri_colour];
-
- /* Scan the colour palette for the colours in this group. */
- brightest = 0x0000;
- for( loop = 0; loop < 16; loop++ )
- if( head->colour_group[loop] == group
- && head->obj_palette[loop] > brightest )
- brightest = head->obj_palette[loop];
-
- /* TODO: replace that > comparison with a real "is colour A brighter */
- /* than colour B?" test. */
-
- return brightest;
- }
-
- /* Convert a given Atari BIOS colour to a "standard" RGB triad ranging */
- /* from 0.0 to 1.0 in each element; note that this assumes the 512- */
- /* colour range of the original Atari ST, and will probably produce */
- /* a bogus RGB triad for STe/TT/Falcon colour ranges (the STe/TT have */
- /* a range of 4096 colours, while the Falcon has 15-bit colour); don't */
- /* use it for that. */
- short atari2rgb( const short atari, RGB_TRIAD *rgb )
- {
- rgb->red = (float)( ( atari & 0x0f00 ) >> 8 )/7.0;
- rgb->green = (float)( ( atari & 0x00f0 ) >> 4 )/7.0;
- rgb->blue = (float)( atari & 0x000f )/7.0;
-
- return 0;
- }
-
- #ifdef LITTLE_ENDIAN
- short swap_short( const short s )
- {
- return ( (s & 0x00ff) << 8 ) | ( (s & 0xff00) >> 8 );
- }
- #endif
-